package service

import (
	"context"
	"fmt"
	"math"
	"time"

	api "github.com/fastknifes/usdt-pay/internal/http/api/interface/v1"
	"github.com/fastknifes/usdt-pay/internal/logic"
	"github.com/fastknifes/usdt-pay/internal/repository/dao"
	"github.com/fastknifes/usdt-pay/internal/repository/model/entity"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/v2/os/gtime"

	"crypto/sha256"
	"encoding/hex"
)

type TradeService struct{}

var page int = 1
var maxNum = 4

func hash(s string) string {
	h := sha256.New()
	h.Write([]byte(s))
	return hex.EncodeToString(h.Sum(nil))
}
func (ts *TradeService) Create(dto api.OrderReq) (amount float64, err error) {

	lastOrder, err := ts.find(dto.Wallet, dto.Network, dto.Amount)

	if err != nil {
		// 处理错误
		return
	}
	ctx := context.Background()
	if lastOrder != nil {
		if hash(lastOrder.Extends) == hash(dto.Extends) {
			amount = lastOrder.PayAmount
			_, err = dao.Trade.Ctx(ctx).Where(g.Map{"id": lastOrder.Id}).Data(g.Map{
				"expired_at": gtime.Now().Add(30 * time.Minute).Unix(),
			}).Update()

			return
		}

		amount = lastOrder.PayAmount + 0.01
		amount = math.Round(amount*100) / 100
	} else {
		amount = dto.Amount
	}

	trade := &entity.Trade{
		Wallet:       dto.Wallet,
		Network:      dto.Network,
		OriginAmount: dto.Amount,
		PayAmount:    amount,
		Callback:     dto.Callback,
		Status:       0,
		Extends:      dto.Extends,
		ExpiredAt:    gtime.Now().Add(30 * time.Minute),
	}

	_, err = dao.Trade.Ctx(ctx).Data(trade).Insert()

	return

}

func (ts *TradeService) Polling() {
	pagesize := 5
	ctx := context.Background()
	var trades []entity.Trade

	totalCount, err := dao.Trade.Ctx(ctx).Where("status", 0).Count()
	if err != nil {
		// 处理错误
		return
	}

	if (page-1)*pagesize >= totalCount {
		page = 1
	}
	dao.Trade.Ctx(ctx).Where("status", 0).Limit(page-1, pagesize).Scan(&trades)
	var result bool = false
	for _, item := range trades {
		fmt.Print(item.Network)
		if item.Network == "TRC20" {
			trc20Logic := logic.Trc20Logic{}
			result = trc20Logic.MatchTrade(item.Wallet, item.PayAmount, item.CreatedAt)
		}

		if item.Network == "Solana" {
			solanaLogic := logic.SolanaLogic{}
			result = solanaLogic.MatchTrade(item.Wallet, item.PayAmount, item.CreatedAt)
		}

		if item.Network == "Polygon" {
			polygonLogic := logic.PolygonLogic{}

			result = polygonLogic.MatchTrade(item.Wallet, item.PayAmount, item.CreatedAt)
		}

		if result {
			ts.savePaidStatus(ctx, item)
		}

	}
	page += 1
}

func (ts *TradeService) savePaidStatus(ctx context.Context, item entity.Trade) {
	dao.Trade.Ctx(ctx).Data(g.Map{"status": 1, "paid_at": gtime.Now()}).Where("id", item.Id).Update()
}

func (ts *TradeService) find(wallet string, network string, amount float64) (*entity.Trade, error) {
	ctx := context.Background()

	lastOrder, err := dao.Trade.Ctx(ctx).Where("status", 0).Where("origin_amount", amount).Where("wallet", wallet).Where("network", network).Order("created_at desc").One()

	if err != nil {
		return nil, err
	}
	if lastOrder == nil {
		return nil, nil // 如果没有找到记录，返回 nil 和 nil 错误
	}

	var result entity.Trade
	if err := lastOrder.Struct(&result); err != nil {
		return nil, err
	}
	return &result, nil
}

func (ts *TradeService) Notify() {

	ctx := context.Background()
	var trades []entity.Trade
	dao.Trade.Ctx(ctx).Where("status", 1).Limit(0, 20).Scan(&trades)
	fmt.Print(trades)
	for _, item := range trades {
		nofityLogic := logic.NotifyLogic{}
		if nofityLogic.TriggerCallBack(item) {
			dao.Trade.Ctx(ctx).Where("id", item.Id).Delete()
			continue
		}
		pushNum := item.PushNum + 1
		if pushNum > maxNum {
			dao.Trade.Ctx(ctx).Data(g.Map{"status": 2}).Where("id", item.Id).Update()
		} else {
			dao.Trade.Ctx(ctx).Data(g.Map{"push_num": pushNum}).Where("id", item.Id).Update()
		}
	}
}
func (tr *TradeService) DeleteTimeout() {
	ctx := context.Background()
	dao.Trade.Ctx(ctx).Where("status", 0).Where("expired_at < NOW()").Delete()
}
